package com.woniuxy.realm;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import com.woniuxy.pojo.User;
import com.woniuxy.service.UserService;

/*
 * 认证：验证账号密码（确定用户身份）
 * 
 * 授权：确定该身份的人有哪些权限
 * 
 * 整合mybatis、spring的步骤
 * 
 * 1.导入包
 * 
 * 2.将db.properties、mybatis-config、spring-context、log4j的配置文件拷贝进来
 * 
 * 3.修改web.xml加载spring-context.xml
 * 
 * 4.编写UserMapper
 * 
 * 5.编写UserService及实现类
 * 
 * 6.在Realm中引入UserService
 * 
 * 7.在doGetAuthenticationInfo()方法中通过UserService调用查询方法
 * 
 * 8.启动程序测试登录
 */
public class UserRealm extends AuthorizingRealm {
    @Resource
    private UserService userService;

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

  //授权的方法：从数据库中读取当前用户有哪些权限
    /*
     * shiro授权分为两大块 角色管理：当前用户是什么身份（限制用户能访问哪些资源：html、jsp、静态资源）
     * 
     * superadmin、admin、teacher、student...
     * 
     * 权限管理：当前用户有哪些权限，具体能做什么事（限制用户能发什么请求）
     * 
     * 对哪些方法、接口有调用的权利
     * 
     * user:delete
     * 
     * student:update
     * 
     * user:pwd:update
     * 
     * 权限管理模块
     * 
     * 最简单的权限管理“至少”应该有5张表
     * 
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("正在查询用户权限");
        // 模拟出查询到的权限
        // 得到账号
        String account = (String) principals.getPrimaryPrincipal();
        int userNumber = Integer.parseInt(account);
        // 通过账号查用户
        User user = userService.findUserByNumber(userNumber);
        Set<String> roles = new HashSet<>();
        List<String> rolesList = user.getRoles();
        for (String string : rolesList) {
            roles.add(string);
        }

        // 假设查询出的是admin
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

        return info;
    }

    // 认证方法：从数据库中查询当前用户的信息（账号、密码等）
    // 如果该方法返回值是null.代表没在数据库查到
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        System.out.println("正在进行认证");
        // token中获取账号
        String account = (String) token.getPrincipal();
		int user_number = Integer.parseInt(account);
        System.out.println("用户提交的账号：" + account);
        // 获取密码(凭证)
        String pwd = new String((char[]) token.getCredentials());
        System.out.println("获取的密码：" + pwd);
        // 假设通过账号从数据库中查询出数据
		User user = userService.findUserByNumber(user_number);
        if (user == null) {
            // 没查到数据，账号不存在
            return null;
        }
        // 1 使用代码方式加密--二者都可使用
        /*
         * SimpleAuthenticationInfo info = new
         * SimpleAuthenticationInfo(user.getAccount(),user.getPwd(), getName());
         */

        // 2 使用配置文件进行加密
        // 获取盐值
        ByteSource salt = ByteSource.Util.bytes(user.getUser_phone());
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(user.getUser_number(), user.getUser_password(), salt,
                        getName());

        return info;
    }

}
